package com.ww.springboot.boot.thread.study.base.other;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.IntConsumer;

/**
 * 描述：
 *
 * @author wanwei
 * @since 2021-11-05 14:52
 */
public class ZeroEvenOdd2 {


    private int n;

    public ZeroEvenOdd2(int n) {
        this.n = n;
    }

    //定义Lock
    private Lock lock = new ReentrantLock();
    //定义Condition
    private Condition conditionZero = lock.newCondition();
    private Condition conditionEven = lock.newCondition();
    private Condition conditionOdd = lock.newCondition();

    //定义标记
    private static int number = 0;

    // printNumber.accept(x) outputs "x", where x is an integer.
    //打印0
    public void zero(IntConsumer printNumber) throws InterruptedException {
        lock.lock();
        try {
            for (int i = 1; i <= n; i++) {
                if (number != 0) {
                    //zero线程等待
                    conditionZero.await();
                }
                printNumber.accept(0);
                if (i % 2 == 1) {
                    number = 1;
                    //唤醒odd线程
                    conditionOdd.signal();
                } else {
                    number = 2;
                    //唤醒even线程
                    conditionEven.signal();
                }
            }
        } finally {
            lock.unlock();
        }
    }

    //打印偶数
    public void even(IntConsumer printNumber) throws InterruptedException {
        lock.lock();
        try {
            for (int i = 2; i <= n; i += 2) {
                if (number != 2) {
                    //even线程等待
                    conditionEven.await();
                }
                printNumber.accept(i);
                number = 0;
                //唤醒zero线程
                conditionZero.signal();
            }
        } finally {
            lock.unlock();
        }
    }

    //打印奇数
    public void odd(IntConsumer printNumber) throws InterruptedException {
        lock.lock();
        try {
            for (int i = 1; i <= n; i += 2) {
                if (number != 1) {
                    //odd线程等待
                    conditionOdd.await();
                }
                printNumber.accept(i);
                number = 0;
                //唤醒zero线程
                conditionZero.signal();
            }
        } finally {
            lock.unlock();
        }
    }
}
